package com.landliu.idea.plugin.cgpt.ui;

import cn.hutool.core.util.ObjectUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.Messages;
import com.intellij.webSymbols.utils.NameCaseUtils;
import com.landliu.idea.plugin.cgpt.common.utils.DBHelper;
import com.landliu.idea.plugin.cgpt.common.utils.JavaType;
import com.landliu.idea.plugin.cgpt.model.po.Table;
import com.landliu.idea.plugin.cgpt.model.vo.CodeGenContextVO;
import com.landliu.idea.plugin.cgpt.service.ProjectGeneratorService;
import com.landliu.idea.plugin.cgpt.service.impl.ProjectGeneratorServiceImpl;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

public class ORMSettingsUI {
    private JPanel main;
    private JButton previousBt;
    private JButton nextBt;
    private JPanel buttonPanel;
    private JPanel settingPanel;
    private JPanel buttonArea;
    private JTabbedPane multiTable;
    private JPanel basicSetting;
    private JTextField packagePath;
    private JTextField moduleName;
    private JTextField authorName;
    private JTextField dataBaseUrl;
    private JTextField portValue;
    private JTextField useName;
    private JTextField passWord;
    private JPanel dataBaseSetting;
    private JTextField dataBaseName;
    private JTextField tablePrefix;
    private JTextField fieldPrefix;
    private JPanel tableSetting;
    private JPanel fieldSetting;
    private JPanel contentPanel;
    private JButton testButton;
    private JTable jTable;
    private JScrollPane jScrollPane;
    private JTabbedPane multiFiledTable;
    private JButton generateButton;

    private List<String> tableNames = new ArrayList<>();

    private String errorMsg;


    private final ProjectGeneratorService projectGeneratorService = new ProjectGeneratorServiceImpl();

    public ORMSettingsUI(Project project, DialogBuilder builder) {

        this.main.setPreferredSize(new Dimension(1000, 400));

        this.packagePath.setText("com.landliu.dev.module");
        this.moduleName.setText(project.getName());
        this.authorName.setText("Liu XiaoJun");

        this.dataBaseUrl.setText("127.0.0.1");
        this.portValue.setText("3306");
        this.useName.setText("root");
        this.passWord.setText("root");
        this.dataBaseName.setText("chapanda_activity");

        this.previousBt.setVisible(false);

        this.jScrollPane.setBorder(null);

        this.generateButton.setVisible(false);

        // 上一页
        this.previousBt.addActionListener(e -> {
            multiTable.setSelectedIndex(multiTable.getSelectedIndex() - 1);
            if(multiTable.getSelectedIndex() == 0){
                previousBt.setVisible(false);
                previousBt.setEnabled(false);
                nextBt.setEnabled(true);
            }
            if(multiTable.getSelectedIndex() == 1){
                testButton.setVisible(true);
            }else{
                testButton.setVisible(false);
                if(multiTable.getSelectedIndex() == 2){
                    multiFiledTable.removeAll();
                }
            }
            if(0 < multiTable.getSelectedIndex()
                    && multiTable.getSelectedIndex() < (multiTable.getTabCount()-1)){
                previousBt.setEnabled(true);
                nextBt.setEnabled(true);
                nextBt.setText("下一页");
            }
        });

        // 下一页
        this.nextBt.addActionListener(e -> {
            this.previousBt.setVisible(true);
            if(multiTable.getSelectedIndex() == 0){
                errorMsg = checkBasicConfig();
                if(ObjectUtil.isNotEmpty(errorMsg)){
                    Messages.showMessageDialog(project, errorMsg, "基础设置检查", Messages.getErrorIcon());
                    return;
                }
            }
            if(multiTable.getSelectedIndex() == 1){
                try {
                    DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                            this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());
                    List<Table> tableList = dbHelper.getAllTableInfo(this.dataBaseName.getText());

                    String[] title = {"是否生成", "表名", "业务名", "备注"};
                    String tableName = "";
                    Object[][] data = new Object[tableList.size()][4];
                    for (int i = 0; i < tableList.size(); i++) {
                        tableName = tableList.get(i).getName();
                        data[i][1] = tableName;
                        data[i][2] = getClassName(tableName);
                        data[i][3] = tableList.get(i).getComment();
                    }

                    DefaultTableModel model = new DefaultTableModel(data, title){
                        @Override
                        public boolean isCellEditable(int row, int column) {
                            return column == 0 || column == 2;
                        }
                    };

                    jTable.setModel(model);
                    TableColumn tc = jTable.getColumnModel().getColumn(0);
                    tc.setCellEditor(new DefaultCellEditor(new JCheckBox()));
                    tc.setCellEditor(jTable.getDefaultEditor(Boolean.class));
                    tc.setCellRenderer(jTable.getDefaultRenderer(Boolean.class));
                    tc.setMaxWidth(100);

                    TableColumn tc2 = jTable.getColumnModel().getColumn(2);
                    tc2.setCellEditor(new DefaultCellEditor(new JTextField()));
                    tc2.setCellEditor(jTable.getDefaultEditor(String.class));
                    tc2.setCellRenderer(jTable.getDefaultRenderer(String.class));

                } catch (Exception exception) {
                    Messages.showMessageDialog(project, exception.getMessage(), "数据库连接错误", Messages.getErrorIcon());
                    return;
                }
            }
            if(multiTable.getSelectedIndex() == 2){
                if(tableNames.isEmpty()){
                    Messages.showMessageDialog(project, "未选择生产代码的数据库表", "表设置检查", Messages.getErrorIcon());
                    return;
                }else{
                    for(String tableName : tableNames){
                        try {
                            DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                                    this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());
                            Table table = dbHelper.getTable(tableName);

                            String[] title = {"字段名", "数据类型", "Java类型", "主键", "是否为空", "属性名", "备注"};
                            String fieldName = "";
                            Object[][] data = new Object[table.getColumns().size()][7];
                            for (int i = 0; i < table.getColumns().size(); i++) {
                                fieldName = table.getColumns().get(i).getName();
                                data[i][0] = fieldName;
                                data[i][1] = table.getColumns().get(i).getDataType();
                                data[i][2] = JavaType.convertType(table.getColumns().get(i).getType()).getSimpleName();
                                data[i][3] = table.getColumns().get(i).isId()?"是":"否";
                                data[i][4] = "NO".equals(table.getColumns().get(i).getIsNullLable())?"否":"是";
                                data[i][5] = getBusinessFieldName(fieldName);
                                data[i][6] = table.getColumns().get(i).getComment();
                            }

                            DefaultTableModel model = new DefaultTableModel(data, title);
                            multiFiledTable.addTab(tableName,new JScrollPane(new JTable(model)));

                        } catch (Exception exception) {
                            Messages.showMessageDialog(project, exception.getMessage(), "数据库连接错误", Messages.getErrorIcon());
                            return;
                        }
                    }
                }
            }
            multiTable.setSelectedIndex(multiTable.getSelectedIndex() + 1);
            if(multiTable.getSelectedIndex() == 0){
                previousBt.setEnabled(false);
                nextBt.setEnabled(true);
            }
            if(0 <multiTable.getSelectedIndex()
                    && multiTable.getSelectedIndex() < (multiTable.getTabCount()-1)){
                previousBt.setEnabled(true);
                nextBt.setEnabled(true);
            }
            if(multiTable.getSelectedIndex() == 1){
                testButton.setVisible(true);
            }else{
                testButton.setVisible(false);
            }
            if(multiTable.getSelectedIndex() == (multiTable.getTabCount()-1)){
                previousBt.setEnabled(true);
                nextBt.setVisible(false);
                generateButton.setVisible(true);
            }
        });

        // 测试数据库链接
        this.testButton.addActionListener(e -> {
            errorMsg = checkDataBaseConfig();
            if(ObjectUtil.isNotEmpty(errorMsg)){
                Messages.showMessageDialog(project, errorMsg, "数据库设置检查", Messages.getErrorIcon());
            }else{
                try {
                    DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                            this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());
                    String mysqlVersion = dbHelper.testDatabase();
                    Messages.showInfoMessage(project, "Connection successful! \r\nMySQL version : " + mysqlVersion, "OK");
                } catch (Exception exception) {
                    Messages.showMessageDialog(project, exception.getMessage(), "数据库设置检查", Messages.getErrorIcon());
                }
            }
        });
        this.generateButton.addActionListener(e -> {
            // 链接DB

            DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                    this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());

            // 组装代码生产上下文
            CodeGenContextVO codeGenContextVO = new CodeGenContextVO();
            codeGenContextVO.setModelPackage(this.packagePath.getText() + ".dal.entity.");
            codeGenContextVO.setServicePackage(this.packagePath.getText() + ".service.");
            codeGenContextVO.setMapperPackage(this.packagePath.getText() + ".dal.mapper.");
            List<Table> tables = new ArrayList<>();
            for (String tableName : tableNames) {
                tables.add(dbHelper.getTable(tableName));
            }
            codeGenContextVO.setTables(tables);

            Application applicationManager = ApplicationManager.getApplication();
            applicationManager.runWriteAction(()-> projectGeneratorService.generation(project, codeGenContextVO));
            applicationManager.exit();

            builder.getDialogWrapper().close(0);
        });

        // 给表添加事件
        this.jTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (1 == e.getClickCount()) {
                    int rowIdx = jTable.rowAtPoint(e.getPoint());
                    Boolean flag = (Boolean) jTable.getValueAt(rowIdx, 0);
                    if (null != flag && flag) {
                        tableNames.add(jTable.getValueAt(rowIdx, 1).toString());
                    } else {
                        tableNames.remove(jTable.getValueAt(rowIdx, 1).toString());
                    }
                }
            }
        });

    }

    /**
     * 获取业务名称
     * @param tableName 表名称
     * @return 业务名称
     */
    private String getClassName(String tableName){
        String tablePrefix = this.tablePrefix.getText();
        if(ObjectUtil.isNotEmpty(tablePrefix)){
            if(tableName.startsWith(tablePrefix)){
                tableName = tableName.substring(tablePrefix.length());
            }
        }
        String className = NameCaseUtils.toCamelCase(tableName);
        className = Character.toUpperCase(className.charAt(0)) + className.substring(1);
        return className;
    }

    /**
     * 获取业务字段名称
     * @param fieldName 字段名称
     * @return 业务字段名称
     */
    private String getBusinessFieldName(String fieldName){
        String fieldPrefixStr = this.fieldPrefix.getText();
        if(ObjectUtil.isNotEmpty(fieldPrefixStr)){
            if(fieldName.startsWith(fieldPrefixStr)){
                fieldName = fieldName.substring(fieldPrefixStr.length());
            }
        }
        String businessFieldName = NameCaseUtils.toCamelCase(fieldName);
        businessFieldName = Character.toUpperCase(businessFieldName.charAt(0)) + businessFieldName.substring(1);
        return businessFieldName;
    }


    /**
     * 检查基础设置
     */
    public String checkBasicConfig(){
        if(ObjectUtil.isEmpty(this.packagePath.getText())){
            return "包路径不能为空!";
        }
        if(ObjectUtil.isEmpty(this.moduleName.getText())){
            return "模块名不能为空!";
        }
        if(ObjectUtil.isEmpty(this.authorName.getText())){
            return "作者不能为空!";
        }
        return null;
    }

    /**
     * 检查数据库设置
     */
    public String checkDataBaseConfig(){
        if(ObjectUtil.isEmpty(this.dataBaseUrl.getText())){
            return "数据库地址不能为空!";
        }
        if(ObjectUtil.isEmpty(this.portValue.getText())){
            return "数据库端口不能为空!";
        }
        if(ObjectUtil.isEmpty(this.useName.getText())){
            return "数据库用户名不能为空!";
        }
        if(ObjectUtil.isEmpty(this.passWord.getText())){
            return "数据库密码不能为空!";
        }
        if(ObjectUtil.isEmpty(this.dataBaseName.getText())){
            return "数据库名称不能为空!";
        }
        return null;
    }

    public JPanel getMainPanel() {
        return main;
    }

}
